/**
 * Definition of peel node entity.
 *
 * \file node.hpp
 * \author tomby
 * \date 04-01-2009
 **/

/*  Copyright (C) 2009  Tomas 'tomby' Bily

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */


#ifndef __DBC_NODE__
#define __DBC_NODE__

namespace dbc {
  namespace peel {

#define IS_DBC_NODE(X) IS_DBC_TYPE(X, dbc::peel::Node)
#define DBC_NODE(X) DBC_TYPE(X, dbc::peel::Node)
#define DBC_NODE_PTR(X) DBC_TYPE_PTR(X, dbc::peel::Node)

    class Edge;

    class Node : public dbc::temporal::StampableEntity
    {
      ENTITY_DEF(Node);

    public:
      class edge_iter
      {
	dbc::PCEntity::Econtainer::iterator it;

      public:
	edge_iter ()
	{}

	edge_iter (dbc::PCEntity::Econtainer::iterator i)
	  : it (i)
	{}

	edge_iter& operator++ ()
	{ ++ it; return *this; }

	edge_iter operator++ (int)
	{ edge_iter tmp = *this; ++it; return tmp; }

	Edge* operator* ()
	{ return reinterpret_cast<Edge*> ((*it).get ()); }

	bool operator== (const edge_iter& i)
	{ return it == i.it; }

	bool operator!= (const edge_iter& i)
	{ return it != i.it; }

	inline dbc::PCEntity::Econtainer::iterator get ()
	{ return it; }
      };

    private:
      int sink_level;
      edge_iter esi_trig_i [2];
      edge_iter esi_trig_o [2];

      inline void add_edge (Edge* edge, dbc::PCEntity::EcontainerPtr& cont, edge_iter* iters);

    protected:
      Node (bool alloc_pc_containers)
	: StampableEntity (alloc_pc_containers)
      {}

    public:
      Node ()
      {}

      virtual void update_state () = 0;

      inline void add_in_edge (Edge* edge);

      inline void add_out_edge (Edge* edge);

      inline edge_iter begin_in_edge (Edge::EdgeType type);
      inline edge_iter end_in_edge (Edge::EdgeType type);

      inline edge_iter begin_out_edge (Edge::EdgeType type);
      inline edge_iter end_out_edge (Edge::EdgeType type);

      inline void set_sink_level (int l)
      { sink_level = l; }

      inline int get_sink_level ()
      { return sink_level; }
    };

  };
};

#endif
